home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / PIL / TiffImagePlugin.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-13  |  20KB  |  696 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. __version__ = '1.3.5'
  5. import Image
  6. import ImageFile
  7. import ImagePalette
  8. import array
  9. import string
  10. import sys
  11.  
  12. try:
  13.     if sys.byteorder == 'little':
  14.         byteorder = 'II'
  15.     else:
  16.         byteorder = 'MM'
  17. except AttributeError:
  18.     if ord(array.array('i', [
  19.         1]).tostring()[0]):
  20.         byteorder = 'II'
  21.     else:
  22.         byteorder = 'MM'
  23. except:
  24.     ord(array.array('i', [
  25.         1]).tostring()[0])
  26.  
  27.  
  28. def il16(c, o = 0):
  29.     return ord(c[o]) + (ord(c[o + 1]) << 8)
  30.  
  31.  
  32. def il32(c, o = 0):
  33.     return ord(c[o]) + (ord(c[o + 1]) << 8) + (ord(c[o + 2]) << 16) + (ord(c[o + 3]) << 24)
  34.  
  35.  
  36. def ol16(i):
  37.     return chr(i & 255) + chr(i >> 8 & 255)
  38.  
  39.  
  40. def ol32(i):
  41.     return chr(i & 255) + chr(i >> 8 & 255) + chr(i >> 16 & 255) + chr(i >> 24 & 255)
  42.  
  43.  
  44. def ib16(c, o = 0):
  45.     return ord(c[o + 1]) + (ord(c[o]) << 8)
  46.  
  47.  
  48. def ib32(c, o = 0):
  49.     return ord(c[o + 3]) + (ord(c[o + 2]) << 8) + (ord(c[o + 1]) << 16) + (ord(c[o]) << 24)
  50.  
  51. IMAGEWIDTH = 256
  52. IMAGELENGTH = 257
  53. BITSPERSAMPLE = 258
  54. COMPRESSION = 259
  55. PHOTOMETRIC_INTERPRETATION = 262
  56. FILLORDER = 266
  57. IMAGEDESCRIPTION = 270
  58. STRIPOFFSETS = 273
  59. SAMPLESPERPIXEL = 277
  60. ROWSPERSTRIP = 278
  61. STRIPBYTECOUNTS = 279
  62. X_RESOLUTION = 282
  63. Y_RESOLUTION = 283
  64. PLANAR_CONFIGURATION = 284
  65. RESOLUTION_UNIT = 296
  66. SOFTWARE = 305
  67. DATE_TIME = 306
  68. ARTIST = 315
  69. PREDICTOR = 317
  70. COLORMAP = 320
  71. EXTRASAMPLES = 338
  72. SAMPLEFORMAT = 339
  73. JPEGTABLES = 347
  74. COPYRIGHT = 33432
  75. IPTC_NAA_CHUNK = 33723
  76. PHOTOSHOP_CHUNK = 34377
  77. COMPRESSION_INFO = {
  78.     1: 'raw',
  79.     2: 'tiff_ccitt',
  80.     3: 'group3',
  81.     4: 'group4',
  82.     5: 'tiff_lzw',
  83.     6: 'tiff_jpeg',
  84.     7: 'jpeg',
  85.     32771: 'tiff_raw_16',
  86.     32773: 'packbits' }
  87. OPEN_INFO = {
  88.     (0, 1, 1, (1,), ()): ('1', '1;I'),
  89.     (0, 1, 2, (1,), ()): ('1', '1;IR'),
  90.     (0, 1, 1, (8,), ()): ('L', 'L;I'),
  91.     (0, 1, 2, (8,), ()): ('L', 'L;IR'),
  92.     (1, 1, 1, (1,), ()): ('1', '1'),
  93.     (1, 1, 2, (1,), ()): ('1', '1;R'),
  94.     (1, 1, 1, (8,), ()): ('L', 'L'),
  95.     (1, 1, 1, (8, 8), (2,)): ('LA', 'LA'),
  96.     (1, 1, 2, (8,), ()): ('L', 'L;R'),
  97.     (1, 1, 1, (16,), ()): ('I;16', 'I;16'),
  98.     (1, 2, 1, (16,), ()): ('I;16S', 'I;16S'),
  99.     (1, 2, 1, (32,), ()): ('I', 'I;32S'),
  100.     (1, 3, 1, (32,), ()): ('F', 'F;32F'),
  101.     (2, 1, 1, (8, 8, 8), ()): ('RGB', 'RGB'),
  102.     (2, 1, 2, (8, 8, 8), ()): ('RGB', 'RGB;R'),
  103.     (2, 1, 1, (8, 8, 8, 8), (0,)): ('RGBX', 'RGBX'),
  104.     (2, 1, 1, (8, 8, 8, 8), (1,)): ('RGBA', 'RGBa'),
  105.     (2, 1, 1, (8, 8, 8, 8), (2,)): ('RGBA', 'RGBA'),
  106.     (2, 1, 1, (8, 8, 8, 8), (999,)): ('RGBA', 'RGBA'),
  107.     (3, 1, 1, (1,), ()): ('P', 'P;1'),
  108.     (3, 1, 2, (1,), ()): ('P', 'P;1R'),
  109.     (3, 1, 1, (2,), ()): ('P', 'P;2'),
  110.     (3, 1, 2, (2,), ()): ('P', 'P;2R'),
  111.     (3, 1, 1, (4,), ()): ('P', 'P;4'),
  112.     (3, 1, 2, (4,), ()): ('P', 'P;4R'),
  113.     (3, 1, 1, (8,), ()): ('P', 'P'),
  114.     (3, 1, 1, (8, 8), (2,)): ('PA', 'PA'),
  115.     (3, 1, 2, (8,), ()): ('P', 'P;R'),
  116.     (5, 1, 1, (8, 8, 8, 8), ()): ('CMYK', 'CMYK'),
  117.     (6, 1, 1, (8, 8, 8), ()): ('YCbCr', 'YCbCr'),
  118.     (8, 1, 1, (8, 8, 8), ()): ('LAB', 'LAB') }
  119. PREFIXES = [
  120.     'MM\x00*',
  121.     'II*\x00',
  122.     'II\xbc\x00']
  123.  
  124. def _accept(prefix):
  125.     return prefix[:4] in PREFIXES
  126.  
  127.  
  128. class ImageFileDirectory:
  129.     
  130.     def __init__(self, prefix = 'II'):
  131.         self.prefix = prefix[:2]
  132.         if self.prefix == 'MM':
  133.             self.i16 = ib16
  134.             self.i32 = ib32
  135.         elif self.prefix == 'II':
  136.             self.i16 = il16
  137.             self.i32 = il32
  138.             self.o16 = ol16
  139.             self.o32 = ol32
  140.         else:
  141.             raise SyntaxError('not a TIFF IFD')
  142.         self.reset()
  143.  
  144.     
  145.     def reset(self):
  146.         self.tags = { }
  147.         self.tagdata = { }
  148.         self.next = None
  149.  
  150.     
  151.     def keys(self):
  152.         return self.tagdata.keys() + self.tags.keys()
  153.  
  154.     
  155.     def items(self):
  156.         items = self.tags.items()
  157.         for tag in self.tagdata.keys():
  158.             items.append((tag, self[tag]))
  159.         
  160.         return items
  161.  
  162.     
  163.     def __len__(self):
  164.         return len(self.tagdata) + len(self.tags)
  165.  
  166.     
  167.     def __getitem__(self, tag):
  168.         
  169.         try:
  170.             return self.tags[tag]
  171.         except KeyError:
  172.             (type, data) = self.tagdata[tag]
  173.             (size, handler) = self.load_dispatch[type]
  174.             self.tags[tag] = data = handler(self, data)
  175.             del self.tagdata[tag]
  176.             return data
  177.  
  178.  
  179.     
  180.     def get(self, tag, default = None):
  181.         
  182.         try:
  183.             return self[tag]
  184.         except KeyError:
  185.             return default
  186.  
  187.  
  188.     
  189.     def getscalar(self, tag, default = None):
  190.         
  191.         try:
  192.             value = self[tag]
  193.             if len(value) != 1:
  194.                 if tag == SAMPLEFORMAT:
  195.                     raise KeyError
  196.                 
  197.                 raise ValueError, 'not a scalar'
  198.             
  199.             return value[0]
  200.         except KeyError:
  201.             if default is None:
  202.                 raise 
  203.             
  204.             return default
  205.  
  206.  
  207.     
  208.     def has_key(self, tag):
  209.         if not self.tags.has_key(tag):
  210.             pass
  211.         return self.tagdata.has_key(tag)
  212.  
  213.     
  214.     def __setitem__(self, tag, value):
  215.         if type(value) is not type(()):
  216.             value = (value,)
  217.         
  218.         self.tags[tag] = value
  219.  
  220.     load_dispatch = { }
  221.     
  222.     def load_byte(self, data):
  223.         l = []
  224.         for i in range(len(data)):
  225.             l.append(ord(data[i]))
  226.         
  227.         return tuple(l)
  228.  
  229.     load_dispatch[1] = (1, load_byte)
  230.     
  231.     def load_string(self, data):
  232.         if data[-1:] == '\x00':
  233.             data = data[:-1]
  234.         
  235.         return data
  236.  
  237.     load_dispatch[2] = (1, load_string)
  238.     
  239.     def load_short(self, data):
  240.         l = []
  241.         for i in range(0, len(data), 2):
  242.             l.append(self.i16(data, i))
  243.         
  244.         return tuple(l)
  245.  
  246.     load_dispatch[3] = (2, load_short)
  247.     
  248.     def load_long(self, data):
  249.         l = []
  250.         for i in range(0, len(data), 4):
  251.             l.append(self.i32(data, i))
  252.         
  253.         return tuple(l)
  254.  
  255.     load_dispatch[4] = (4, load_long)
  256.     
  257.     def load_rational(self, data):
  258.         l = []
  259.         for i in range(0, len(data), 8):
  260.             l.append((self.i32(data, i), self.i32(data, i + 4)))
  261.         
  262.         return tuple(l)
  263.  
  264.     load_dispatch[5] = (8, load_rational)
  265.     
  266.     def load_float(self, data):
  267.         a = array.array('f', data)
  268.         if self.prefix != byteorder:
  269.             a.byteswap()
  270.         
  271.         return tuple(a)
  272.  
  273.     load_dispatch[11] = (4, load_float)
  274.     
  275.     def load_double(self, data):
  276.         a = array.array('d', data)
  277.         if self.prefix != byteorder:
  278.             a.byteswap()
  279.         
  280.         return tuple(a)
  281.  
  282.     load_dispatch[12] = (8, load_double)
  283.     
  284.     def load_undefined(self, data):
  285.         return data
  286.  
  287.     load_dispatch[7] = (1, load_undefined)
  288.     
  289.     def load(self, fp):
  290.         self.reset()
  291.         i16 = self.i16
  292.         i32 = self.i32
  293.         for i in range(i16(fp.read(2))):
  294.             ifd = fp.read(12)
  295.             tag = i16(ifd)
  296.             typ = i16(ifd, 2)
  297.             if Image.DEBUG:
  298.                 import TiffTags as TiffTags
  299.                 tagname = TiffTags.TAGS.get(tag, 'unknown')
  300.                 typname = TiffTags.TYPES.get(typ, 'unknown')
  301.                 print 'tag: %s (%d)' % (tagname, tag), '- type: %s (%d)' % (typname, typ),
  302.             
  303.             
  304.             try:
  305.                 dispatch = self.load_dispatch[typ]
  306.             except KeyError:
  307.                 if Image.DEBUG:
  308.                     print '- unsupported type', typ
  309.                     continue
  310.                 continue
  311.  
  312.             (size, handler) = dispatch
  313.             size = size * i32(ifd, 4)
  314.             if size > 4:
  315.                 here = fp.tell()
  316.                 fp.seek(i32(ifd, 8))
  317.                 data = ImageFile._safe_read(fp, size)
  318.                 fp.seek(here)
  319.             else:
  320.                 data = ifd[8:8 + size]
  321.             if len(data) != size:
  322.                 raise IOError, 'not enough data'
  323.             
  324.             self.tagdata[tag] = (typ, data)
  325.             if Image.DEBUG:
  326.                 if tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK):
  327.                     print '- value: <table: %d bytes>' % size
  328.                 else:
  329.                     print '- value:', self[tag]
  330.             tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK)
  331.         
  332.         self.next = i32(fp.read(4))
  333.  
  334.     
  335.     def save(self, fp):
  336.         o16 = self.o16
  337.         o32 = self.o32
  338.         fp.write(o16(len(self.tags)))
  339.         tags = self.tags.items()
  340.         tags.sort()
  341.         directory = []
  342.         append = directory.append
  343.         offset = fp.tell() + len(self.tags) * 12 + 4
  344.         stripoffsets = None
  345.         for tag, value in tags:
  346.             if Image.DEBUG:
  347.                 import TiffTags
  348.                 tagname = TiffTags.TAGS.get(tag, 'unknown')
  349.                 print 'save: %s (%d)' % (tagname, tag), '- value:', value
  350.             
  351.             if type(value[0]) is type(''):
  352.                 typ = 2
  353.                 data = value = string.join(value, '\x00') + '\x00'
  354.             elif tag == STRIPOFFSETS:
  355.                 stripoffsets = len(directory)
  356.                 typ = 4
  357.             elif tag in (X_RESOLUTION, Y_RESOLUTION):
  358.                 typ = 5
  359.             else:
  360.                 typ = 3
  361.                 for v in value:
  362.                     if v >= 65536:
  363.                         typ = 4
  364.                         continue
  365.                 
  366.             if typ == 3:
  367.                 data = string.join(map(o16, value), '')
  368.             else:
  369.                 data = string.join(map(o32, value), '')
  370.             if len(data) == 4:
  371.                 append((tag, typ, len(value), data, ''))
  372.                 continue
  373.             if len(data) < 4:
  374.                 append((tag, typ, len(value), data + (4 - len(data)) * '\x00', ''))
  375.                 continue
  376.             count = len(value)
  377.             if typ == 5:
  378.                 count = count / 2
  379.             
  380.             append((tag, typ, count, o32(offset), data))
  381.             offset = offset + len(data)
  382.             if offset & 1:
  383.                 offset = offset + 1
  384.                 continue
  385.         
  386.         if stripoffsets is not None:
  387.             (tag, typ, count, value, data) = directory[stripoffsets]
  388.             value = o32(self.i32(value) + offset)
  389.             directory[stripoffsets] = (tag, typ, count, value, data)
  390.         
  391.         for tag, typ, count, value, data in directory:
  392.             if Image.DEBUG > 1:
  393.                 print tag, typ, count, repr(value), repr(data)
  394.             
  395.             fp.write(o16(tag) + o16(typ) + o32(count) + value)
  396.         
  397.         fp.write('\x00\x00\x00\x00')
  398.         for tag, typ, count, value, data in directory:
  399.             fp.write(data)
  400.             if len(data) & 1:
  401.                 fp.write('\x00')
  402.                 continue
  403.         
  404.         return offset
  405.  
  406.  
  407.  
  408. class TiffImageFile(ImageFile.ImageFile):
  409.     format = 'TIFF'
  410.     format_description = 'Adobe TIFF'
  411.     
  412.     def _open(self):
  413.         ifh = self.fp.read(8)
  414.         if ifh[:4] not in PREFIXES:
  415.             raise SyntaxError, 'not a TIFF file'
  416.         
  417.         self.tag = self.ifd = ImageFileDirectory(ifh[:2])
  418.         self._TiffImageFile__first = self._TiffImageFile__next = self.ifd.i32(ifh, 4)
  419.         self._TiffImageFile__frame = -1
  420.         self._TiffImageFile__fp = self.fp
  421.         self._seek(0)
  422.  
  423.     
  424.     def seek(self, frame):
  425.         if frame < 0:
  426.             frame = 0
  427.         
  428.         self._seek(frame)
  429.  
  430.     
  431.     def tell(self):
  432.         return self._tell()
  433.  
  434.     
  435.     def _seek(self, frame):
  436.         self.fp = self._TiffImageFile__fp
  437.         if frame < self._TiffImageFile__frame:
  438.             self._TiffImageFile__frame = -1
  439.             self._TiffImageFile__next = self._TiffImageFile__first
  440.         
  441.         while self._TiffImageFile__frame < frame:
  442.             if not self._TiffImageFile__next:
  443.                 raise EOFError, 'no more images in TIFF file'
  444.             
  445.             self.fp.seek(self._TiffImageFile__next)
  446.             self.tag.load(self.fp)
  447.             self._TiffImageFile__next = self.tag.next
  448.             self._TiffImageFile__frame = self._TiffImageFile__frame + 1
  449.         self._setup()
  450.  
  451.     
  452.     def _tell(self):
  453.         return self._TiffImageFile__frame
  454.  
  455.     
  456.     def _decoder(self, rawmode, layer):
  457.         args = None
  458.         if rawmode == 'RGB' and self._planar_configuration == 2:
  459.             rawmode = rawmode[layer]
  460.         
  461.         compression = self._compression
  462.         if compression == 'raw':
  463.             args = (rawmode, 0, 1)
  464.         elif compression == 'jpeg':
  465.             args = (rawmode, '')
  466.             if self.tag.has_key(JPEGTABLES):
  467.                 self.tile_prefix = self.tag[JPEGTABLES]
  468.             
  469.         elif compression == 'packbits':
  470.             args = rawmode
  471.         elif compression == 'tiff_lzw':
  472.             args = rawmode
  473.             if self.tag.has_key(317):
  474.                 self.decoderconfig = (self.tag[PREDICTOR][0],)
  475.             
  476.         
  477.         return args
  478.  
  479.     
  480.     def _setup(self):
  481.         if self.tag.has_key(48129):
  482.             raise IOError, 'Windows Media Photo files not yet supported'
  483.         
  484.         getscalar = self.tag.getscalar
  485.         self._compression = COMPRESSION_INFO[getscalar(COMPRESSION, 1)]
  486.         self._planar_configuration = getscalar(PLANAR_CONFIGURATION, 1)
  487.         photo = getscalar(PHOTOMETRIC_INTERPRETATION, 0)
  488.         fillorder = getscalar(FILLORDER, 1)
  489.         if Image.DEBUG:
  490.             print '*** Summary ***'
  491.             print '- compression:', self._compression
  492.             print '- photometric_interpretation:', photo
  493.             print '- planar_configuration:', self._planar_configuration
  494.             print '- fill_order:', fillorder
  495.         
  496.         xsize = getscalar(IMAGEWIDTH)
  497.         ysize = getscalar(IMAGELENGTH)
  498.         self.size = (xsize, ysize)
  499.         if Image.DEBUG:
  500.             print '- size:', self.size
  501.         
  502.         format = getscalar(SAMPLEFORMAT, 1)
  503.         key = (photo, format, fillorder, self.tag.get(BITSPERSAMPLE, (1,)), self.tag.get(EXTRASAMPLES, ()))
  504.         if Image.DEBUG:
  505.             print 'format key:', key
  506.         
  507.         
  508.         try:
  509.             (self.mode, rawmode) = OPEN_INFO[key]
  510.         except KeyError:
  511.             if Image.DEBUG:
  512.                 print '- unsupported format'
  513.             
  514.             raise SyntaxError, 'unknown pixel mode'
  515.  
  516.         if Image.DEBUG:
  517.             print '- raw mode:', rawmode
  518.             print '- pil mode:', self.mode
  519.         
  520.         self.info['compression'] = self._compression
  521.         xdpi = getscalar(X_RESOLUTION, (1, 1))
  522.         ydpi = getscalar(Y_RESOLUTION, (1, 1))
  523.         if xdpi and ydpi and getscalar(RESOLUTION_UNIT, 1) == 1:
  524.             if not xdpi[1]:
  525.                 pass
  526.             xdpi = xdpi[0] / 1
  527.             if not ydpi[1]:
  528.                 pass
  529.             ydpi = ydpi[0] / 1
  530.             self.info['dpi'] = (xdpi, ydpi)
  531.         
  532.         x = y = l = 0
  533.         self.tile = []
  534.         if self.tag.has_key(STRIPOFFSETS):
  535.             h = getscalar(ROWSPERSTRIP, ysize)
  536.             w = self.size[0]
  537.             a = None
  538.             for o in self.tag[STRIPOFFSETS]:
  539.                 if not a:
  540.                     a = self._decoder(rawmode, l)
  541.                 
  542.                 self.tile.append((self._compression, (0, min(y, ysize), w, min(y + h, ysize)), o, a))
  543.                 y = y + h
  544.                 if y >= self.size[1]:
  545.                     x = y = 0
  546.                     l = l + 1
  547.                     a = None
  548.                     continue
  549.             
  550.         elif self.tag.has_key(324):
  551.             w = getscalar(322)
  552.             h = getscalar(323)
  553.             a = None
  554.             for o in self.tag[324]:
  555.                 if not a:
  556.                     a = self._decoder(rawmode, l)
  557.                 
  558.                 self.tile.append((self._compression, (x, y, x + w, y + h), o, a))
  559.                 x = x + w
  560.                 if x >= self.size[0]:
  561.                     x = 0
  562.                     y = y + h
  563.                     if y >= self.size[1]:
  564.                         x = y = 0
  565.                         l = l + 1
  566.                         a = None
  567.                     
  568.                 y >= self.size[1]
  569.             
  570.         elif Image.DEBUG:
  571.             print '- unsupported data organization'
  572.         
  573.         raise SyntaxError('unknown data organization')
  574.         if self.mode == 'P':
  575.             palette = map((lambda a: chr(a / 256)), self.tag[COLORMAP])
  576.             self.palette = ImagePalette.raw('RGB;L', string.join(palette, ''))
  577.         
  578.  
  579.  
  580. SAVE_INFO = {
  581.     '1': ('1', 1, 1, (1,), None),
  582.     'L': ('L', 1, 1, (8,), None),
  583.     'LA': ('LA', 1, 1, (8, 8), 2),
  584.     'P': ('P', 3, 1, (8,), None),
  585.     'PA': ('PA', 3, 1, (8, 8), 2),
  586.     'I': ('I;32S', 1, 2, (32,), None),
  587.     'I;16': ('I;16', 1, 1, (16,), None),
  588.     'I;16S': ('I;16S', 1, 2, (16,), None),
  589.     'F': ('F;32F', 1, 3, (32,), None),
  590.     'RGB': ('RGB', 2, 1, (8, 8, 8), None),
  591.     'RGBX': ('RGBX', 2, 1, (8, 8, 8, 8), 0),
  592.     'RGBA': ('RGBA', 2, 1, (8, 8, 8, 8), 2),
  593.     'CMYK': ('CMYK', 5, 1, (8, 8, 8, 8), None),
  594.     'YCbCr': ('YCbCr', 6, 1, (8, 8, 8), None),
  595.     'LAB': ('LAB', 8, 1, (8, 8, 8), None) }
  596.  
  597. def _cvt_res(value):
  598.     if type(value) in (type([]), type(())):
  599.         return value
  600.     
  601.     if type(value) == type(1):
  602.         return (value, 1)
  603.     
  604.     value = float(value)
  605.     return (int(value * 65536), 65536)
  606.  
  607.  
  608. def _save(im, fp, filename):
  609.     
  610.     try:
  611.         (rawmode, photo, format, bits, extra) = SAVE_INFO[im.mode]
  612.     except KeyError:
  613.         raise IOError, 'cannot write mode %s as TIFF' % im.mode
  614.  
  615.     ifd = ImageFileDirectory()
  616.     fp.write(ifd.prefix + ifd.o16(42) + ifd.o32(8))
  617.     ifd[IMAGEWIDTH] = im.size[0]
  618.     ifd[IMAGELENGTH] = im.size[1]
  619.     if hasattr(im, 'tag'):
  620.         for key in (RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION):
  621.             if im.tag.tagdata.has_key(key):
  622.                 ifd[key] = im.tag.tagdata.get(key)
  623.                 continue
  624.         
  625.     
  626.     if im.encoderinfo.has_key('description'):
  627.         ifd[IMAGEDESCRIPTION] = im.encoderinfo['description']
  628.     
  629.     if im.encoderinfo.has_key('resolution'):
  630.         ifd[X_RESOLUTION] = ifd[Y_RESOLUTION] = _cvt_res(im.encoderinfo['resolution'])
  631.     
  632.     if im.encoderinfo.has_key('x resolution'):
  633.         ifd[X_RESOLUTION] = _cvt_res(im.encoderinfo['x resolution'])
  634.     
  635.     if im.encoderinfo.has_key('y resolution'):
  636.         ifd[Y_RESOLUTION] = _cvt_res(im.encoderinfo['y resolution'])
  637.     
  638.     if im.encoderinfo.has_key('resolution unit'):
  639.         unit = im.encoderinfo['resolution unit']
  640.         if unit == 'inch':
  641.             ifd[RESOLUTION_UNIT] = 2
  642.         elif unit == 'cm' or unit == 'centimeter':
  643.             ifd[RESOLUTION_UNIT] = 3
  644.         else:
  645.             ifd[RESOLUTION_UNIT] = 1
  646.     
  647.     if im.encoderinfo.has_key('software'):
  648.         ifd[SOFTWARE] = im.encoderinfo['software']
  649.     
  650.     if im.encoderinfo.has_key('date time'):
  651.         ifd[DATE_TIME] = im.encoderinfo['date time']
  652.     
  653.     if im.encoderinfo.has_key('artist'):
  654.         ifd[ARTIST] = im.encoderinfo['artist']
  655.     
  656.     if im.encoderinfo.has_key('copyright'):
  657.         ifd[COPYRIGHT] = im.encoderinfo['copyright']
  658.     
  659.     dpi = im.encoderinfo.get('dpi')
  660.     if dpi:
  661.         ifd[RESOLUTION_UNIT] = 1
  662.         ifd[X_RESOLUTION] = _cvt_res(dpi[0])
  663.         ifd[Y_RESOLUTION] = _cvt_res(dpi[1])
  664.     
  665.     if bits != (1,):
  666.         ifd[BITSPERSAMPLE] = bits
  667.         if len(bits) != 1:
  668.             ifd[SAMPLESPERPIXEL] = len(bits)
  669.         
  670.     
  671.     if extra is not None:
  672.         ifd[EXTRASAMPLES] = extra
  673.     
  674.     if format != 1:
  675.         ifd[SAMPLEFORMAT] = format
  676.     
  677.     ifd[PHOTOMETRIC_INTERPRETATION] = photo
  678.     if im.mode == 'P':
  679.         lut = im.im.getpalette('RGB', 'RGB;L')
  680.         ifd[COLORMAP] = tuple(map((lambda v: ord(v) * 256), lut))
  681.     
  682.     stride = len(bits) * ((im.size[0] * bits[0] + 7) / 8)
  683.     ifd[ROWSPERSTRIP] = im.size[1]
  684.     ifd[STRIPBYTECOUNTS] = stride * im.size[1]
  685.     ifd[STRIPOFFSETS] = 0
  686.     ifd[COMPRESSION] = 1
  687.     offset = ifd.save(fp)
  688.     ImageFile._save(im, fp, [
  689.         ('raw', (0, 0) + im.size, offset, (rawmode, stride, 1))])
  690.  
  691. Image.register_open('TIFF', TiffImageFile, _accept)
  692. Image.register_save('TIFF', _save)
  693. Image.register_extension('TIFF', '.tif')
  694. Image.register_extension('TIFF', '.tiff')
  695. Image.register_mime('TIFF', 'image/tiff')
  696.